package com.lzj.demo.design.iterator;

import cn.hutool.core.collection.CollectionUtil;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class GroupStructure implements Collection<Employee,Link>{
    /**
     * 组织id
     * */
    private Long groupId;
    /**
     * 组织名称
     * */
    private String groupName;
    /**
     * 雇员列表
     * */
    private Map<Long,Employee> employeeMap = new ConcurrentHashMap<>();
    /**
     * 组织架构关系
     * */
    private Map<Long, List<Link>> linkMap = new ConcurrentHashMap<>();
    /**
     * 反向关系链
     * */
    private Map<Long,Long> invertedMap = new ConcurrentHashMap<>();

    public GroupStructure(Long groupId, String groupName) {
        this.groupId = groupId;
        this.groupName = groupName;
    }

    @Override
    public boolean add(Employee e) {
        return Objects.nonNull(employeeMap.put(e.getUId(),e));
    }

    @Override
    public boolean remove(Employee e) {
        return Objects.nonNull(employeeMap.get(e.getUId()));
    }

    @Override
    public boolean addLink(Long key, Link link) {
        invertedMap.put(link.getToId(),link.getFromId());
        if(linkMap.containsKey(key)){
            return linkMap.get(key).add(link);
        }else {
            List<Link> links = new LinkedList<>();
            links.add(link);
            linkMap.put(key,links);
        }
        return false;
    }

    @Override
    public boolean removeLink(Long key) {
        return Objects.nonNull(linkMap.remove(key));
    }

    @Override
    public Iterator<Employee> iterator() {
        return new Iterator<Employee>() {
            Map<Long,Integer> keyMap = new HashMap<>();
            int totalIdx = 0;
            private Long fromId = groupId;
            private Long toId = groupId;

            @Override
            public boolean hasNext() {
                return totalIdx < employeeMap.size();
            }

            @Override
            public Employee next() {
                List<Link> links = linkMap.get(toId);
                int currentIdx = getCurrentIdx(toId);
                if(CollectionUtil.isEmpty(links)){
                    currentIdx = getCurrentIdx(fromId);
                    links = linkMap.get(fromId);
                }
                while (currentIdx > links.size()-1){
                    fromId = invertedMap.get(fromId);
                    currentIdx = getCurrentIdx(fromId);
                    links = linkMap.get(fromId);
                }
                Link link = links.get(currentIdx);
                toId = link.getToId();
                fromId = link.getFromId();
                totalIdx++;
                return employeeMap.get(link.getToId());
            }

            /**
             * 给每个层级定义宽带,遍历进度
             * */
            public int getCurrentIdx(Long key){
                int idx = 0;
                if(keyMap.containsKey(key)){
                    idx = keyMap.get(key);
                    keyMap.put(key,++idx);
                }else {
                    keyMap.put(key,idx);
                }
                return idx;
            }
        };
    }
}
